package com.jlf.starter.advice.filter;

import com.jlf.core.annotation.filter.FilterProcessor;
import com.jlf.core.annotation.filter.ParameterFilter;
import com.jlf.starter.advice.entity.ParameterFilterWrapper;
import org.joor.Reflect;

import java.lang.annotation.*;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Comparator;
import java.util.List;

/**
 * 请求参数的过滤处理
 *
 * @author wujr
 * 2021/1/14
 * @version 1.0
 * 变更历史
 * [wujr 2021/1/14 1.0 新增]
 */
public class RequestParameterFilter {
    public static void filter(Object body, Field field) {
        Object object = Reflect.on(body).get(field.getName());
        if (null == object) {
            return;
        } else if (!(object instanceof String) && !object.getClass().isArray() && !Collection.class.isAssignableFrom(object.getClass())) {
            // 该对象不是字符串，也不是数组，也不是集合
            return;
        }
        List<ParameterFilterWrapper> filters = loadFilter(field);
        if (filters.isEmpty()) {
            return;
        }
        filters.sort(Comparator.comparingInt(ParameterFilterWrapper::getOrder));
        for (ParameterFilterWrapper filter : filters) {
            object = doFilterObject(filter, object);
        }

        Reflect.on(body).set(field.getName(), object);
    }
    private static Object doFilterObject(ParameterFilterWrapper filter, Object object) {
        FilterProcessor<?> processor;
        try {
            processor = filter.getFilter().processor().getDeclaredConstructor().newInstance();
        }catch (Exception e) {
            return object;
        }
        if (object instanceof String) {
            object = processor.filter(filter.getAnnotation(), (String)object);
        } else if (object.getClass().isArray()) {
            // 这是数组
            Object[] values = (Object[])object;
            for (int index = 0; index < values.length; ++ index) {
                Object value = values[index];
                if (!(value instanceof String)) {
                    break;
                }
                values[index] = processor.filter(filter.getAnnotation(), (String)value);
            }
        }
        return object;
    }
    private static List<ParameterFilterWrapper> loadFilter(Field field) {
        Annotation[] annotations = field.getAnnotations();
        List<ParameterFilterWrapper> output = new ArrayList<>(annotations.length);
        for (Annotation annotation : annotations) {
            if (annotation.annotationType().isAssignableFrom(ParameterFilter.class)) {
                // 该注解本身就是InputFilter注解
                output.add(new ParameterFilterWrapper(annotation, (ParameterFilter)annotation));
            } else {
                loadFilter(annotation, output);
            }
        }

        return output;
    }

    static boolean isBasicAnnotation(Annotation annotation){
        return annotation.annotationType().isAssignableFrom(Documented.class) ||
                annotation.annotationType().isAssignableFrom(Target.class) ||
                annotation.annotationType().isAssignableFrom(Retention.class) ||
                annotation.annotationType().isAssignableFrom(Repeatable.class);
    }
    private static void loadFilter(Annotation annotation, List<ParameterFilterWrapper> output){
        Annotation[] annotations = annotation.annotationType().getAnnotations();
        for (Annotation sub : annotations) {
            if (isBasicAnnotation(sub)) {
                continue;
            }
            if (sub.annotationType().isAssignableFrom(ParameterFilter.class)) {
                output.add(new ParameterFilterWrapper(annotation, (ParameterFilter)sub));
            } else {
                loadFilter(sub, output);
            }
        }
    }
}
